package by.gravity.common.utils;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

import android.app.Activity;
import android.content.Context;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Point;
import android.graphics.PorterDuff.Mode;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.media.ExifInterface;
import android.media.MediaScannerConnection;
import android.net.Uri;
import android.provider.MediaStore;
import android.util.Log;
import android.view.Display;
import android.view.WindowManager;

public class ImageUtil {

	private static final String TAG = ImageUtil.class.getSimpleName();

	public static final String HTTP = "http:/";

	public static final String HTTPS = "https:/";

	public static Uri tryGetImageFromBadDevice(Activity activity) {
		// Describe the columns you'd like to have returned.
		// Selecting from the Thumbnails location gives you both
		// the Thumbnail Image ID, as well as the original image
		// ID
		String[] projection = {
				MediaStore.Images.Thumbnails._ID, // The columns
				// we want
				MediaStore.Images.Thumbnails.IMAGE_ID, MediaStore.Images.Thumbnails.KIND,
				MediaStore.Images.Thumbnails.DATA };
		String selection = MediaStore.Images.Thumbnails.KIND + "=" + // Select
																		// only
																		// mini's
				MediaStore.Images.Thumbnails.MINI_KIND;

		String sort = MediaStore.Images.Thumbnails._ID + " DESC";

		// At the moment, this is a bit of a hack, as I'm
		// returning ALL images, and just taking the latest one.
		// There is a better way to narrow this down I think
		// with a WHERE clause which is currently the selection
		// variable
		Cursor myCursor = activity.managedQuery(MediaStore.Images.Thumbnails.EXTERNAL_CONTENT_URI, projection,
				selection, null, sort);

		long imageId = 0l;
		long thumbnailImageId = 0l;
		String thumbnailPath = "";

		try {
			myCursor.moveToFirst();
			imageId = myCursor.getLong(myCursor.getColumnIndexOrThrow(MediaStore.Images.Thumbnails.IMAGE_ID));
			thumbnailImageId = myCursor.getLong(myCursor.getColumnIndexOrThrow(MediaStore.Images.Thumbnails._ID));
			thumbnailPath = myCursor.getString(myCursor.getColumnIndexOrThrow(MediaStore.Images.Thumbnails.DATA));
		} finally {
			myCursor.close();
		}

		// Create new Cursor to obtain the file Path for the
		// large image

		String[] largeFileProjection = { MediaStore.Images.ImageColumns._ID, MediaStore.Images.ImageColumns.DATA };

		String largeFileSort = MediaStore.Images.ImageColumns._ID + " DESC";
		myCursor = activity.managedQuery(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, largeFileProjection, null, null,
				largeFileSort);
		String largeImagePath = "";

		try {
			myCursor.moveToFirst();

			// This will actually give yo uthe file path
			// location of the image.
			largeImagePath = myCursor.getString(myCursor.getColumnIndexOrThrow(MediaStore.Images.ImageColumns.DATA));
			Log.d("BD", "lmp" + largeImagePath);
		} finally {
			myCursor.close();
		}
		// These are the two URI's you'll be interested in. They
		// give you a handle to the actual images
		Uri uriLargeImage = Uri.withAppendedPath(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, String.valueOf(imageId));
		Log.d("BD", "uriLargeImage" + uriLargeImage);
		return uriLargeImage;
		/*
		 * Uri uriThumbnailImage = Uri .withAppendedPath(
		 * MediaStore.Images.Thumbnails.EXTERNAL_CONTENT_URI,
		 * String.valueOf(thumbnailImageId));
		 */

		// I've left out the remaining code, as all I do is
		// assign the URI's to my own objects anyways...
	}

	public static String getHashUrl(String url) {
		byte[] defaultBytes = url.getBytes();
		try {
			MessageDigest algorithm = MessageDigest.getInstance("MD5");
			algorithm.reset();
			algorithm.update(defaultBytes);
			byte messageDigest[] = algorithm.digest();

			StringBuffer hexString = new StringBuffer();
			for (int i = 0; i < messageDigest.length; i++) {
				hexString.append(Integer.toHexString(0xFF & messageDigest[i]));
			}
			return hexString.toString();
		} catch (NoSuchAlgorithmException nsae) {

		} catch (StackOverflowError e) {

		}
		return null;
	}

	public static boolean saveImageToFile(String absolutePath, Bitmap bitmap, String fileName) throws IOException {
		File file = new File(absolutePath, fileName);
		return saveImageToFile(file, bitmap);
	}

	public static boolean saveImageToFile(String absolutePath, Bitmap bitmap) throws IOException {
		File file = new File(absolutePath);
		return saveImageToFile(file, bitmap);
	}

	private static boolean saveImageToFile(File file, Bitmap bitmap) throws IOException {
		if (bitmap == null) {
			return false;
		}
		OutputStream outStream = null;
		outStream = new FileOutputStream(file);

		bitmap.compress(Bitmap.CompressFormat.JPEG, 100, outStream);
		outStream.flush();
		outStream.close();
		System.gc();
		return true;
	}

	public static Bitmap loadFromFile(String filePath) {
		Bitmap bitmap = BitmapFactory.decodeFile(filePath);
		if (bitmap != null) {
			return bitmap;
		}

		return null;
	}

	public static Boolean fileExists(String filePath) {
		File file = new File(filePath);
		return file.exists();

	}

	public static Bitmap getRoundedCornersImage(Bitmap source, int radiusPixels) {
		if (source == null) {
			// we cant proccess null image, go out
			return null;
		}
		final int sourceWidth = source.getWidth();
		final int sourceHeight = source.getHeight();
		final Bitmap output = Bitmap.createBitmap(sourceWidth, sourceHeight, Bitmap.Config.ARGB_8888);
		final Canvas canvas = new Canvas(output);

		final int color = 0xFF000000;
		final Paint paint = new Paint();
		paint.setColor(color);

		final Rect rect = new Rect(0, 0, sourceWidth, sourceHeight);
		final RectF rectF = new RectF(rect);

		paint.setAntiAlias(true);
		canvas.drawARGB(0, 0, 0, 0);
		canvas.drawRoundRect(rectF, radiusPixels, radiusPixels, paint);

		paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
		canvas.drawBitmap(source, 0, 0, paint);

		return output;
	}

	public static Bitmap compressImageWithAlpha(Context context, String filePath) throws IOException {
		return compressImage(context, filePath, -1);
	}

	public static Bitmap compressImage(Context context, String filePath) throws IOException {
		return compressImage(context, filePath, -1);
	}

	public static Bitmap compressImage(Context context, String filePath, int ratio) throws IOException {
		Uri uri = getUri(filePath);
		InputStream is = null;
		try {

			int compress;
			if (ratio < 1) {

				try {
					is = context.getContentResolver().openInputStream(uri);
				} catch (Exception e) {
					throw new IOException(e.getMessage());
				}
				BitmapFactory.Options dbo = new BitmapFactory.Options();
				dbo.inJustDecodeBounds = true;
				Bitmap srcBitmap = BitmapFactory.decodeStream(is, null, dbo);
				is.close();
				clear(srcBitmap);
				WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
				Display display = wm.getDefaultDisplay();
				compress = dbo.outHeight / display.getHeight();
			} else {
				compress = ratio;
			}

			try {
				is = context.getContentResolver().openInputStream(uri);
			} catch (Exception e) {
				throw new IOException(e.getMessage());
			}
			BitmapFactory.Options dbo2 = new BitmapFactory.Options();
			dbo2.inSampleSize = compress;
			Bitmap srcBitmap = BitmapFactory.decodeStream(is, null, dbo2);

			return srcBitmap;
		} catch (FileNotFoundException e) {
			Log.e(TAG, "when compress image file not found", e);
		} finally {
			is.close();
		}
		return null;
	}

	public static Bitmap getCorrectlyOrientedImage(Context context, String path, double q, boolean isSquare,
			boolean needToResizeToScreen) throws IOException {
		Uri uri = Uri.fromFile(new File(path));
		return getCorrectlyOrientedImage(context, uri, q, isSquare, needToResizeToScreen);
	}

	public static Bitmap getCorrectlyOrientedImage(Context context, Uri photoUri, double q, boolean isSquare,
			boolean needToResizeToScreen) throws IOException {
		InputStream is = null;
		try {
			is = context.getContentResolver().openInputStream(photoUri);
		} catch (Exception e) {
			throw new IOException(e.getMessage());
		}

		BitmapFactory.Options dbo = new BitmapFactory.Options();
		dbo.inJustDecodeBounds = true;
		Bitmap srcBitmap = BitmapFactory.decodeStream(is, null, dbo);
		is.close();
		clear(srcBitmap);

		int rotatedWidth, rotatedHeight;
		int orientation = getOrientation(context, photoUri);

		if (orientation == 90 || orientation == 270) {
			rotatedWidth = dbo.outHeight;
			rotatedHeight = dbo.outWidth;
		} else {
			rotatedWidth = dbo.outWidth;
			rotatedHeight = dbo.outHeight;
		}

		is = context.getContentResolver().openInputStream(photoUri);
		Display display = ((WindowManager) context.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
		int width = display.getWidth();
		int height = display.getHeight();
		if (needToResizeToScreen && (rotatedWidth > width || rotatedHeight > height)) {
			float widthRatio = ((float) rotatedWidth) / ((float) width);
			float heightRatio = ((float) rotatedHeight) / ((float) height);
			float maxRatio = Math.max(widthRatio, heightRatio);

			// Create the bitmap from file
			BitmapFactory.Options options = new BitmapFactory.Options();
			if (q > 1) {
				options.inSampleSize = (int) maxRatio * (int) q;
			} else {
				options.inSampleSize = (int) maxRatio;
			}
			srcBitmap = BitmapFactory.decodeStream(is, null, options);
		} else {
			BitmapFactory.Options options = new BitmapFactory.Options();
			if (q > 1) {
				options.inSampleSize = (int) q;
			}
			srcBitmap = BitmapFactory.decodeStream(is, null, options);
		}
		is.close();

		/*
		 * if the orientation is not 0 (or -1, which means we don't know), we
		 * have to do a rotation.
		 */
		if (orientation > 0) {
			Matrix matrix = new Matrix();
			matrix.postRotate(orientation);

			Bitmap rotatedBitmap = Bitmap.createBitmap(srcBitmap, 0, 0, srcBitmap.getWidth(), srcBitmap.getHeight(),
					matrix, true);
			clear(srcBitmap);
			srcBitmap = rotatedBitmap;
		}
		if (!isSquare && q >= 1) {
			return srcBitmap;
		}
		int w = (int) ((double) srcBitmap.getWidth() * q);
		int h = (int) ((double) srcBitmap.getHeight() * q);
		Bitmap result = Bitmap.createScaledBitmap(srcBitmap, w, h, true);
		clear(srcBitmap);
		if (!isSquare) {
			return result;
		}
		if (w > h) {
			int margin = result.getWidth() / 2 - result.getHeight() / 2;
			Bitmap squareResult = Bitmap.createBitmap(result, margin, 0, result.getHeight(), result.getHeight());
			clear(result);
			result = squareResult;
		} else if (w < h) {
			int margin = result.getHeight() / 2 - result.getWidth() / 2;
			Bitmap squareResult = Bitmap.createBitmap(result, 0, margin, result.getWidth(), result.getWidth());
			clear(result);
			result = squareResult;
		}

		return result;
	}

	public static int getOrientation(Context context, Uri photoUri) {
		/* it's on the external media. */
		Cursor cursor = context.getContentResolver().query(photoUri,
				new String[] { MediaStore.Images.ImageColumns.ORIENTATION, MediaStore.Images.ImageColumns.DATA }, null,
				null, null);

		if (cursor == null || cursor.getCount() != 1) {
			return -1;
		}

		cursor.moveToFirst();
		int orientation = cursor.getInt(0);
		if (orientation == 0 || orientation == -1) {
			String filePath = cursor.getString(1);
			if (filePath != null) {
				try {
					ExifInterface exif = new ExifInterface(filePath);
					String exifOrientation = exif.getAttribute(ExifInterface.TAG_ORIENTATION);
					Log.d("DB", "" + exifOrientation);
					if (exifOrientation != null) {
						if (exifOrientation.equals("6")) {
							return 90;
						}
						if (exifOrientation.equals("8")) {
							return 270;
						}
						if (exifOrientation.equals("1")) {
							return 0;
						}
						if (exifOrientation.equals("3")) {
							return 180;
						}
					}
				} catch (IOException e) {
					// TODO Auto-generated catch block 6 - vert; 1 hor
					e.printStackTrace();
				} // Since API Level 5
			}
		}
		return orientation;
	}

	public static String getFilePathImage(Context context, Uri contentUri) {
		String[] proj = { MediaStore.Images.Media.DATA };
		Cursor cursor = context.getContentResolver().query(contentUri, proj, null, null, null);
		if (cursor != null) {
			int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
			cursor.moveToFirst();
			return cursor.getString(column_index);
		}
		return null;
	}

	public static void clear(Bitmap src) {
		if (src != null) {
			if (!src.isRecycled()) {
				src.recycle();
			}
			src = null;
			System.gc();
		}
	}

	public static Point getPictureSize(Context context, String filePath) throws IOException {
		InputStream is = null;
		Uri uri = getUri(filePath);
		try {
			is = context.getContentResolver().openInputStream(uri);
		} catch (Exception e) {
			throw new IOException(e.getMessage());
		}

		BitmapFactory.Options dbo = new BitmapFactory.Options();
		dbo.inJustDecodeBounds = true;
		Bitmap srcBitmap = BitmapFactory.decodeStream(is, null, dbo);
		is.close();
		clear(srcBitmap);

		return new Point(dbo.outWidth, dbo.outHeight);
	}

	public static void saveBitmapToCard(Bitmap bitmap, String filePath, String fileName) {
		FileOutputStream out;
		if (!fileName.contains(".")) {
			fileName += ".jpg";
		}
		try {
			out = new FileOutputStream(filePath + File.separator + fileName);
			bitmap.compress(Bitmap.CompressFormat.JPEG, 100, out);
			ImageUtil.clear(bitmap);
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}
	}

	public static void saveBitmapToCard(Bitmap bitmap, String filePath) {
		FileOutputStream out;
		try {
			out = new FileOutputStream(filePath);
			bitmap.compress(Bitmap.CompressFormat.JPEG, 100, out);
			ImageUtil.clear(bitmap);
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}
	}

	public static void shareImageToGallery(Context context, String filePath) {
		MediaScannerConnection.scanFile(context, new String[] { filePath }, null, null);
	}

	public static Integer getRatioImageToScreen(Context context, String filePath) throws IOException {
		WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
		Display display = wm.getDefaultDisplay();

		return getRatioImageToScreen(context, filePath, display.getHeight());

	}

	public static Integer getRatioImageToScreen(Context context, String filePath, int currentHeigth) throws IOException {

		InputStream is = null;
		Uri uri = ImageUtil.getUri(filePath);
		is = context.getContentResolver().openInputStream(uri);

		BitmapFactory.Options dbo = new BitmapFactory.Options();
		dbo.inJustDecodeBounds = true;
		Bitmap srcBitmap = BitmapFactory.decodeStream(is, null, dbo);
		is.close();
		clear(srcBitmap);

		if (dbo.outHeight / currentHeigth < 1) {
			return 1;
		}

		return dbo.outHeight / currentHeigth;

	}

	public static Uri getUri(String filePath) {
		if (isOnlineFile(filePath)) {
			return Uri.parse(filePath);
		} else {
			return Uri.fromFile(new File(filePath));
		}
	}

	public static Boolean isOnlineFile(String filePath) {
		if (filePath.contains("google") || filePath.startsWith("http") || filePath.startsWith("https")) {
			return true;
		} else {
			return false;
		}

	}

	public static String getFileNameFromFilePath(String filePath) {
		int lastIndexFileName;
		int dotLastIndex = filePath.lastIndexOf(".");
		if (dotLastIndex > filePath.lastIndexOf("/")) {
			lastIndexFileName = filePath.length();
		} else {
			lastIndexFileName = dotLastIndex;
		}

		if (filePath.contains("google")) {
			return filePath.substring(filePath.lastIndexOf("/") + 1);
		}

		return filePath.substring(filePath.lastIndexOf("/") + 1, lastIndexFileName);

	}

	public static String getFileNameFromUrl(String url) {
		return url.substring(url.lastIndexOf("/") + 1);
	}

	public static String getFilePathImage(Uri contentUri, Context context) {
		String[] proj = { MediaStore.Images.Media.DATA };
		Cursor cursor = context.getContentResolver().query(contentUri, proj, null, null, null);
		if (cursor != null) {
			int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
			cursor.moveToFirst();
			return cursor.getString(column_index);
		}
		return null;
	}

	public static Bitmap convertDrawableToBitmap(Drawable drawable) {
		return ((BitmapDrawable) drawable).getBitmap();
	}

}
